// File:       ios.c++
// Version:    1.00
// Author:     (c) Miles Sabin, 1997
// Purpose:    approximation to ANSI C++ ios

// Change log:
//  12/02/97   v. 1.00
//  20/02/97   Added sync_with_stdio().
//             Added sync check on iostream_default_stdiosync.
//  24/03/97   Modified to conform more closely to Dec '96 WP.
//  25/03/97   Revamped stdio syncing a bit.

#include "ios.h"

#include "newcasts.h"


// Implementation of ios_base

ios_base::ios_base()
  {}

ios_base::~ios_base()
  { delete[] arrays_; }

int ios_base::xalloc()
{
  return index_++;
}

ios_base::long_and_ptr& ios_base::get_array_element(int index)
  {
    // implementation idea idea borrowed from libg++

    ++index;
    if(arrays_ != 0 && arrays_[0].i > index)
      return arrays_[index];

    long old_size = (arrays_ == 0 ? 0 : arrays_[0].i);
    long new_size = index+1;

    long_and_ptr* new_arrays = new long_and_ptr[new_size];

    int i;

    for(i = 1; i < old_size; ++i)
      new_arrays[i] = arrays_[i];

    for(/* i = old_size */; i < new_size; ++i)
    {
      new_arrays[i].i = 0;
      new_arrays[i].p = 0;
    }

    new_arrays[0].i = new_size;

    delete[] arrays_;
    arrays_ = new_arrays;

    return arrays_[index];
  }

long& ios_base::iword(int index)
  { return get_array_element(index).i; }

void*& ios_base::pword(int index)
  { return get_array_element(index).p; }

void ios_base::init()
  {
    fmtflags_ = skipws|dec;
    precision_ = 6;
    width_ = 0;
    arrays_ = 0;
  }

void ios_base::copyfmt(ios_base const& rhs)
  {
    fmtflags_ = rhs.fmtflags_;
    precision_ = rhs.precision_;
    width_ = rhs.width_;

    for(int i = 0; i < index_; ++i)
    {
      iword(i) = const_cast(ios_base&, rhs).iword(i);
      pword(i) = const_cast(ios_base&, rhs).pword(i);
    }
  }

bool ios_base::sync_with_stdio(bool sync)
{
  bool old_sync = sync_with_stdio_;
  sync_with_stdio_ = sync;
  return old_sync;
}

int ios_base:: index_ = 1;
bool ios_base::sync_with_stdio_ = true;


// implementation of basic_ios_char

basic_ios_char::basic_ios_char(basic_streambuf_char* sb)
  { init(sb); }

basic_ios_char::~basic_ios_char()
  {}

void basic_ios_char::init(basic_streambuf_char* sb)
  {
    ios_base::init();
    sb_ = sb;
    exceptions_ = goodbit;
    iostate_ = (sb == 0 ? badbit : goodbit);
    fill_char_ = ' ';
    tie_ = 0;
  }

void basic_ios_char::clear(iostate state)
  {
    iostate_ = state;
    if((iostate_&exceptions_) != 0)
      throw(failure(""));
  }

void basic_ios_char::setstate(iostate state)
  { clear(rdstate()|state); }

void basic_ios_char::exceptions(iostate except)
  {
    exceptions_ = except;
    clear(rdstate());
  }

basic_streambuf_char* basic_ios_char::rdbuf(basic_streambuf_char* sb)
  {
    basic_streambuf_char* old_sb = sb_;
    sb_ = sb;
    clear(sb_ == 0 ? badbit : 0);
    return old_sb;
  }

basic_ios_char& basic_ios_char::copyfmt(basic_ios_char const& rhs)
  {
    ios_base::copyfmt(rhs);
    fill(rhs.fill());
    tie(rhs.tie());
    exceptions(rhs.exceptions());
    return *this;
  }


// Implementation of ios_base free fns

ios_base& boolalpha(ios_base& str)
{
  str.setf(ios_base::boolalpha);
  return str;
}

ios_base& noboolalpha(ios_base& str)
{
  str.unsetf(ios_base::boolalpha);
  return str;
}

ios_base& showbase(ios_base& str)
{
  str.setf(ios_base::showbase);
  return str;
}

ios_base& noshowbase(ios_base& str)
{
  str.unsetf(ios_base::showbase);
  return str;
}

ios_base& showpoint(ios_base& str)
{
  str.setf(ios_base::showpoint);
  return str;
}

ios_base& noshowpoint(ios_base& str)
{
  str.unsetf(ios_base::showpoint);
  return str;
}

ios_base& showpos(ios_base& str)
{
  str.setf(ios_base::showpos);
  return str;
}

ios_base& noshowpos(ios_base& str)
{
  str.unsetf(ios_base::showpos);
  return str;
}

ios_base& skipws(ios_base& str)
{
  str.setf(ios_base::skipws);
  return str;
}

ios_base& noskipws(ios_base& str)
{
  str.unsetf(ios_base::skipws);
  return str;
}

ios_base& uppercase(ios_base& str)
{
  str.setf(ios_base::uppercase);
  return str;
}

ios_base& nouppercase(ios_base& str)
{
  str.unsetf(ios_base::uppercase);
  return str;
}

ios_base& internal(ios_base& str)
{
  str.setf(ios_base::internal, ios_base::adjustfield);
  return str;
}

ios_base& left(ios_base& str)
{
  str.setf(ios_base::left, ios_base::adjustfield);
  return str;
}

ios_base& right(ios_base& str)
{
  str.setf(ios_base::right, ios_base::adjustfield);
  return str;
}

ios_base& dec(ios_base& str)
{
  str.setf(ios_base::dec, ios_base::basefield);
  return str;
}

ios_base& hex(ios_base& str)
{
  str.setf(ios_base::hex, ios_base::basefield);
  return str;
}

ios_base& oct(ios_base& str)
{
  str.setf(ios_base::oct, ios_base::basefield);
  return str;
}

ios_base& fixed(ios_base& str)
{
  str.setf(ios_base::fixed, ios_base::floatfield);
  return str;
}

ios_base& scientific(ios_base& str)
{
  str.setf(ios_base::scientific, ios_base::floatfield);
  return str;
}
